home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / WEAPON.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  10KB  |  381 lines

  1. /*    SCCS Id: @(#)weapon.c    3.0    89/11/19
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  *    This module contains code for calculation of "to hit" and damage
  7.  *    bonuses for any given weapon used, as well as weapons selection
  8.  *    code for monsters.
  9.  */
  10. #include    "hack.h"
  11.  
  12. #ifdef OVLB
  13.  
  14. static const char NEARDATA kebabable[] = { S_XORN, S_DRAGON, S_NAGA, S_GIANT, 0 };
  15.  
  16. /*
  17.  *     hitval returns an integer representing the "to hit" bonuses
  18.  *    of "otmp" against the monster type "ptr".
  19.  */
  20. int
  21. hitval(otmp, ptr)
  22. struct    obj *otmp;
  23. struct    permonst *ptr;
  24. {
  25.     int    tmp = 0;
  26.  
  27.     if(otmp->olet == WEAPON_SYM || otmp->otyp == PICK_AXE
  28.                         || otmp->otyp == UNICORN_HORN)
  29.         tmp += otmp->spe;
  30.  
  31. /*    Put weapon specific "to hit" bonuses in below:        */
  32.     switch(otmp->otyp) {
  33.  
  34. #ifdef TOLKIEN
  35.         case DWARVISH_MATTOCK:
  36. #endif
  37.         case TWO_HANDED_SWORD:    tmp -= 1; break;
  38.         case KATANA:        tmp += 1; break;
  39. #ifdef TOLKIEN
  40.         case ELVEN_DAGGER:
  41.         case ORCISH_DAGGER:
  42. #endif
  43.         case DAGGER:
  44.         case SCALPEL:
  45.         case ATHAME:
  46.         case SHURIKEN:        tmp += 2; break;
  47. #ifdef WORM
  48.         case CRYSKNIFE:        tmp += 3; break;
  49. #endif
  50.     }
  51.  
  52. /*    Put weapon vs. monster type "to hit" bonuses in below:    */
  53.  
  54.     /* Blessed weapons used against undead or demons */
  55.     if(otmp->olet == WEAPON_SYM && otmp->blessed &&
  56.        (is_demon(ptr) || is_undead(ptr))) tmp += 2;
  57.  
  58.     if(otmp->otyp >= SPEAR && otmp->otyp <= JAVELIN &&
  59.        index(kebabable, ptr->mlet)) tmp += 2;
  60.  
  61. /*    Put specially named weapon "to hit" bonuses in below:    */
  62. #ifdef NAMED_ITEMS
  63.     tmp += spec_abon(otmp, ptr);
  64. #endif
  65.     return(tmp);
  66. }
  67.  
  68. /*
  69.  *     dmgval returns an integer representing the damage bonuses
  70.  *    of "otmp" against the monster type "ptr".
  71.  */
  72. int
  73. dmgval(otmp, ptr)
  74. struct    obj *otmp;
  75. struct    permonst *ptr;
  76. {
  77.     int    tmp = 0;
  78.  
  79.     if(otmp->otyp == CREAM_PIE)    return(0);
  80.  
  81.     if(ptr->msize >= MZ_HUMAN) {
  82.         if(objects[otmp->otyp].wldam)
  83.         tmp = rnd(objects[otmp->otyp].wldam);
  84.         switch (otmp->otyp) {
  85.         case CROSSBOW_BOLT:
  86.         case MORNING_STAR:
  87.         case PARTISAN:
  88. #ifdef TOLKIEN
  89.         case ELVEN_BROADSWORD:
  90. #endif
  91.         case BROADSWORD:    tmp++; break;
  92.  
  93.         case FLAIL:
  94.         case RANSEUR:
  95.         case VOULGE:        tmp += rnd(4); break;
  96.  
  97.         case ACID_VENOM:
  98.         case HALBERD:
  99.         case SPETUM:        tmp += rnd(6); break;
  100.  
  101.         case BARDICHE:
  102.         case TRIDENT:        tmp += d(2,4); break;
  103.  
  104. #ifdef TOLKIEN
  105.         case DWARVISH_MATTOCK:
  106. #endif
  107.         case TWO_HANDED_SWORD:    tmp += d(2,6); break;
  108.         }
  109.     } else {
  110.         if(objects[otmp->otyp].wsdam)
  111.         tmp = rnd(objects[otmp->otyp].wsdam);
  112.         switch (otmp->otyp) {
  113.         case CROSSBOW_BOLT:
  114.         case MACE:
  115.         case WAR_HAMMER:
  116.         case FLAIL:
  117.         case SPETUM:
  118.         case TRIDENT:        tmp++; break;
  119.  
  120.         case BARDICHE:
  121.         case BILL_GUISARME:
  122.         case GUISARME:
  123.         case LUCERN_HAMMER:
  124.         case MORNING_STAR:
  125.         case RANSEUR:
  126.         case BROADSWORD:
  127. #ifdef TOLKIEN
  128.         case ELVEN_BROADSWORD:
  129. #endif
  130.         case VOULGE:        tmp += rnd(4); break;
  131.  
  132.         case ACID_VENOM:    tmp += rnd(6); break;
  133.         }
  134.     }
  135.     if (otmp->otyp == BULLWHIP && thick_skinned(ptr))
  136.         /* thick skinned/scaled creatures don't feel it */
  137.         tmp = 0;
  138.     if (otmp->olet == WEAPON_SYM || otmp->otyp == PICK_AXE
  139.                         || otmp->otyp == UNICORN_HORN)
  140.         tmp += otmp->spe;
  141.  
  142. /*    Put weapon vs. monster type damage bonuses in below:    */
  143.     if(otmp->olet == WEAPON_SYM) {
  144.         if (otmp->blessed && (is_undead(ptr) || is_demon(ptr)))
  145.         tmp += rnd(4);
  146.     }
  147.  
  148. /*    Put specially named weapon damage bonuses in below:    */
  149. #ifdef NAMED_ITEMS
  150.     tmp += spec_dbon(otmp, ptr, tmp);
  151. #endif
  152.     return(tmp);
  153. }
  154.  
  155. void
  156. set_uasmon() {        /* update the "uasmon" structure */
  157.  
  158. #ifdef POLYSELF
  159.     if(u.umonnum >= 0) uasmon = &mons[u.umonnum];
  160.     else {
  161. #endif
  162.  
  163.         uasmon = &playermon;
  164.         playermon.mlevel = u.ulevel;
  165.         playermon.ac = u.uac;
  166.         playermon.mr = (u.ulevel > 8) ? 5 * (u.ulevel-7) : u.ulevel;
  167. #ifdef POLYSELF
  168.     }
  169. #endif
  170.     return;
  171. }
  172.  
  173. #endif /* OVLB */
  174. #ifdef OVL0
  175.  
  176. #define    Oselect(x)    if((otmp = m_carrying(mtmp, x))) return(otmp);
  177.  
  178. #ifdef TOLKIEN
  179. static const int NEARDATA rwep[] =
  180.     { DWARVISH_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, JAVELIN,
  181.       SHURIKEN, SILVER_ARROW, ELVEN_ARROW, ARROW, ORCISH_ARROW,
  182.       CROSSBOW_BOLT, ELVEN_DAGGER, DAGGER, ORCISH_DAGGER, KNIFE, ROCK,
  183.       LOADSTONE, LUCKSTONE, DART, /* BOOMERANG, */ CREAM_PIE
  184.       /* note: CREAM_PIE should NOT be #ifdef KOPS */
  185.       };
  186. #else
  187. static const int NEARDATA rwep[] =
  188.     { SPEAR, JAVELIN, SHURIKEN, SILVER_ARROW, ARROW, CROSSBOW_BOLT,
  189.       DAGGER, KNIFE, ROCK, LOADSTONE, LUCKSTONE, DART, /* BOOMERANG, */
  190.       CREAM_PIE
  191.       /* note: CREAM_PIE should NOT be #ifdef KOPS */
  192.       };
  193. #endif
  194.  
  195. struct obj *
  196. select_rwep(mtmp)    /* select a ranged weapon for the monster */
  197. register struct monst *mtmp;
  198. {
  199.     register struct obj *otmp;
  200.     int i;
  201. #ifdef KOPS
  202.     char mlet = mtmp->data->mlet;
  203.  
  204.     if(mlet == S_KOP)    /* pies are first choice for Kops */
  205.         Oselect(CREAM_PIE);
  206. #endif
  207.     if(throws_rocks(mtmp->data))    /* ...boulders for giants */
  208.         Oselect(BOULDER);
  209.     /*
  210.      * other than these two specific cases, always select the
  211.      * most potent ranged weapon to hand.
  212.      */
  213.     for (i = 0; i < SIZE(rwep); i++) {
  214.         boolean no_propellor = FALSE;
  215.         int prop;
  216.  
  217.         /* shooting gems from slings; this goes just before the darts */
  218.         if (rwep[i]==DART && !likes_gems(mtmp->data)
  219.             && m_carrying(mtmp, SLING)) {
  220.         for(otmp=mtmp->minvent; otmp; otmp=otmp->nobj) {
  221.             if(otmp->olet==GEM_SYM &&
  222.                 (otmp->otyp != LOADSTONE || !otmp->cursed))
  223.             return(otmp);
  224.         }
  225.         }
  226.         prop = (objects[rwep[i]]).w_propellor;
  227.         if (prop > 0) {
  228.         switch (prop) {
  229.         case WP_BOW:
  230. #ifdef TOLKIEN
  231.           no_propellor = !(m_carrying(mtmp, BOW) ||
  232.                    m_carrying(mtmp, ELVEN_BOW) ||
  233.                    m_carrying(mtmp, ORCISH_BOW));
  234. #else
  235.           no_propellor = !(m_carrying(mtmp, BOW));
  236. #endif
  237.           break;
  238.         case WP_SLING:
  239.           no_propellor = !(m_carrying(mtmp, SLING));
  240.           break;
  241.         case WP_CROSSBOW:
  242.           no_propellor = !(m_carrying(mtmp, CROSSBOW));
  243.         }
  244.           }
  245.         if (!no_propellor) {
  246.         /* Note: cannot use m_carrying for loadstones, since it will
  247.          * always select the first object of a type, and maybe the
  248.          * monster is carrying two but only the first is unthrowable.
  249.          */
  250.         if (rwep[i] != LOADSTONE) {
  251.             Oselect(rwep[i]);
  252.         } else for(otmp=mtmp->minvent; otmp; otmp=otmp->nobj) {
  253.             if (otmp->otyp == LOADSTONE && !otmp->cursed)
  254.             return otmp;
  255.         }
  256.         }
  257.       }
  258.  
  259.     /* failure */
  260.     return (struct obj *)0;
  261. }
  262.  
  263. #ifdef TOLKIEN
  264. /* 0 = used by any monster; 1 = only used by strong monsters */
  265. static const int NEARDATA hwep[][2] =
  266.     { {DWARVISH_MATTOCK,1}, {TWO_HANDED_SWORD,1}, {KATANA,0},
  267.       {UNICORN_HORN,1},
  268. #ifdef WORM
  269.       {CRYSKNIFE,0},
  270. #endif
  271.       {TRIDENT,0}, {LONG_SWORD,0}, {ELVEN_BROADSWORD,0}, {BROADSWORD,0},
  272.       {LUCERN_HAMMER,1}, {SCIMITAR,1}, {HALBERD,1}, {PARTISAN,1},
  273.       {LANCE,1}, {FAUCHARD,1}, {BILL_GUISARME,1}, {BEC_DE_CORBIN,1},
  274.       {GUISARME,1}, {RANSEUR,1}, {SPETUM,1}, {VOULGE,1}, {BARDICHE,0},
  275.       {MORNING_STAR,0}, {GLAIVE,0}, {ELVEN_SHORT_SWORD,0},
  276.       {DWARVISH_SHORT_SWORD,0}, {SHORT_SWORD,0}, {ORCISH_SHORT_SWORD,0},
  277.       {MACE,0}, {AXE,0}, {DWARVISH_SPEAR,0}, {ELVEN_SPEAR,0}, {SPEAR,0},
  278.       {ORCISH_SPEAR,0}, {FLAIL,0}, {QUARTERSTAFF,1}, {JAVELIN,0},
  279.       {AKLYS,0}, {CLUB,0}, {PICK_AXE,0},
  280. #ifdef KOPS
  281.       {RUBBER_HOSE,0},
  282. #endif /* KOPS */
  283.       {WAR_HAMMER,0}, {ELVEN_DAGGER,0}, {DAGGER,0}, {ORCISH_DAGGER,0},
  284.       {ATHAME,0}, {SCALPEL,0}, {KNIFE,0},
  285. #ifdef WORM
  286.       {WORM_TOOTH,0},
  287. #endif
  288.       {BULLWHIP,0}
  289.     };
  290. #else /* TOLKIEN */
  291. /* 0 = used by any monster; 1 = only used by strong monsters */
  292. static const int NEARDATA hwep[][2] =
  293.     { {TWO_HANDED_SWORD,1}, {KATANA,0}, {UNICORN_HORN,1},
  294. #ifdef WORM
  295.       {CRYSKNIFE,0},
  296. #endif
  297.       {TRIDENT,0}, {LONG_SWORD,0}, {BROADSWORD,0}, {LUCERN_HAMMER,1},
  298.       {SCIMITAR,1}, {HALBERD,1}, {PARTISAN,1}, {LANCE,1}, {FAUCHARD,1},
  299.       {BILL_GUISARME,1}, {BEC_DE_CORBIN,1}, {GUISARME,1}, {RANSEUR,1},
  300.       {SPETUM,1}, {VOULGE,1}, {BARDICHE,0}, {MORNING_STAR,0}, {GLAIVE,0},
  301.       {SHORT_SWORD,0}, {MACE,0}, {AXE,0}, {SPEAR,0}, {FLAIL,0},
  302.       {QUARTERSTAFF,1}, {JAVELIN,0}, {AKLYS,0}, {CLUB,0}, {PICK_AXE,0},
  303. #ifdef KOPS
  304.       {RUBBER_HOSE,0},
  305. #endif /* KOPS */
  306.       {WAR_HAMMER,0}, {DAGGER,0}, {ATHAME,0}, {SCALPEL,0}, {KNIFE,0},
  307. #ifdef WORM
  308.       {WORM_TOOTH,0},
  309. #endif
  310.       {BULLWHIP,0}
  311.     };
  312. #endif /* TOLKIEN */
  313.  
  314. struct obj *
  315. select_hwep(mtmp)    /* select a hand to hand weapon for the monster */
  316. register struct monst *mtmp;
  317. {
  318.     register struct obj *otmp;
  319.     int i;
  320.     boolean strong = strongmonst(mtmp->data);
  321.  
  322.     if(is_giant(mtmp->data))    /* giants just love to use clubs */
  323.         Oselect(CLUB);
  324.  
  325.     /* only strong monsters can wield big (esp. long) weapons */
  326.     /* all monsters can wield the remaining weapons */
  327.     for (i = 0; i < SIZE(hwep); i++)
  328.         if (strong || hwep[i][1]==0)
  329.         Oselect(hwep[i][0]);
  330.  
  331.     /* failure */
  332.     return (struct obj *)0;
  333. }
  334.  
  335. int
  336. abon() {    /* attack bonus for strength & dexterity */
  337.     int    sbon;
  338.  
  339. #ifdef POLYSELF
  340.     if (u.umonnum >= 0) return(adj_lev(&mons[u.umonnum])-3);
  341. #endif
  342.     if(ACURR(A_STR) < 6) sbon = -2;
  343.     else if(ACURR(A_STR) < 8) sbon = -1;
  344.     else if(ACURR(A_STR) < 17) sbon = 0;
  345.     else if(ACURR(A_STR) < 69) sbon = 1;    /* up to 18/50 */
  346.     else if(ACURR(A_STR) < 118) sbon = 2;
  347.     else sbon = 3;
  348. /*
  349.  *    Temporary kludge - make it a bit easier for a low level character
  350.  *               to hit until we tune the game a little better.
  351.  */
  352.     sbon += (u.ulevel < 3) ? 2 : (u.ulevel < 5) ? 1 : 0;
  353.  
  354.     if(ACURR(A_DEX) < 4) return(sbon-3);
  355.     else if(ACURR(A_DEX) < 6) return(sbon-2);
  356.     else if(ACURR(A_DEX) < 8) return(sbon-1);
  357.     else if(ACURR(A_DEX) < 14) return(sbon);
  358.     else return(sbon+ACURR(A_DEX)-14);
  359. }
  360.  
  361. #endif /* OVL0 */
  362. #ifdef OVL1
  363.  
  364. int
  365. dbon() {    /* damage bonus for strength */
  366. #ifdef POLYSELF
  367.     if (u.umonnum >= 0) return(0);
  368. #endif
  369.  
  370.     if(ACURR(A_STR) < 6) return(-1);
  371.     else if(ACURR(A_STR) < 16) return(0);
  372.     else if(ACURR(A_STR) < 18) return(1);
  373.     else if(ACURR(A_STR) == 18) return(2);        /* up to 18 */
  374.     else if(ACURR(A_STR) < 94) return(3);        /* up to 18/75 */
  375.     else if(ACURR(A_STR) < 109) return(4);        /* up to 18/90 */
  376.     else if(ACURR(A_STR) < 118) return(5);    /* up to 18/99 */
  377.     else return(6);
  378. }
  379.  
  380. #endif /* OVL1 */
  381.